package com.atguigu.tingshu.album.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Maps;

import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Override
    public Map<String, Object> uploadTrack(MultipartFile file) {

        return vodService.getVodMediaMap(file);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo) {

        TrackInfoServiceImpl proxy = (TrackInfoServiceImpl) AopContext.currentProxy();

        Long userId = AuthContextHolder.getUserId();

        // 1.保存声音的基本信息
        TrackInfo trackInfo = new TrackInfo();

        // 1.1 声音基本属性通过拷贝赋值
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        // 1.2 声音的其它属性手动赋值
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
        trackInfo.setUserId(userId);
        LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId());
        wrapper.orderByDesc(TrackInfo::getOrderNum);
        wrapper.last("limit 1");
        TrackInfo maxOrderNumTrackInfo = trackInfoMapper.selectOne(wrapper);
        Integer orderNum = maxOrderNumTrackInfo == null ? 1 : maxOrderNumTrackInfo.getOrderNum() + 1;
        trackInfo.setOrderNum(orderNum);  // 序列号

        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (trackMediaInfoVo != null) {
            trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));// 声音时长
            trackInfo.setMediaFileId(trackInfoVo.getMediaFileId()); //声音在vod中的文件id
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());  // 声音在vod中的地址
            trackInfo.setMediaSize(trackMediaInfoVo.getSize()); // 声音的大小
            trackInfo.setMediaType(trackMediaInfoVo.getType()); // 声音的类型
        }
        trackInfoMapper.insert(trackInfo);

        // 2.保存声音的统计信息
        proxy.initTrackStat(trackInfo.getId());


        // 3.修改这个声音对应专辑的包含声音级数
        Long albumId = trackInfo.getAlbumId();
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if (albumInfo != null) {
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        }
        albumInfoMapper.updateById(albumInfo);
    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(IPage<TrackListVo> trackInfoVoPage, TrackInfoQuery trackInfoQuery) {

        return trackInfoMapper.findUserTrackPage(trackInfoVoPage, trackInfoQuery);
    }

    @Override
    public TrackInfo getTrackInfo(Long trackId) {
        return trackInfoMapper.selectById(trackId);
    }

    @Override
    public void updateTrackInfo(TrackInfoVo trackInfoVo, Long trackId) {

        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

        if (null == trackInfo) {
            throw new GuiguException(201, "声音不存在");
        }
        String oldMediaFileId = trackInfo.getMediaFileId();
        String newMediaFileId = trackInfoVo.getMediaFileId();
        BeanUtils.copyProperties(trackInfoVo, trackInfo);

        if (!StringUtils.isEmpty(newMediaFileId) && !oldMediaFileId.equals(newMediaFileId)) {
            // 获取新声音媒体信息 存放数据库
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(newMediaFileId);
            if (mediaInfo != null) {
                trackInfo.setMediaDuration(new BigDecimal(mediaInfo.getDuration()));
                trackInfo.setMediaType(mediaInfo.getType());
                trackInfo.setMediaFileId(newMediaFileId);
                trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
                trackInfo.setMediaSize(mediaInfo.getSize());
            }
        }
        trackInfoMapper.updateById(trackInfo);
    }


    @Transactional(rollbackFor = Exception.class)
    public void initTrackStat(Long trackId) {
        ArrayList<String> trackStatTypes = new ArrayList<>();
        trackStatTypes.add(SystemConstant.TRACK_STAT_PLAY);
        trackStatTypes.add(SystemConstant.TRACK_STAT_COLLECT);
        trackStatTypes.add(SystemConstant.TRACK_STAT_PRAISE);
        trackStatTypes.add(SystemConstant.TRACK_STAT_COMMENT);
        for (String trackStatType : trackStatTypes) {
            TrackStat trackStat = new TrackStat();
            trackStat.setTrackId(trackId);
            trackStat.setStatType(trackStatType);
            trackStat.setStatNum(0);
            trackStatMapper.insert(trackStat);
        }
    }

}
